// GameStartData.cs
//
// Copyright (c) 2007 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Linq;

using Supremacy.Diplomacy;
using Supremacy.Entities;
using Supremacy.Personnel;
using Supremacy.Tech;
using Supremacy.Text;
using Supremacy.Universe;
using Supremacy.AI;

namespace Supremacy.Game
{
    /// <summary>
    /// Contains the data sent to the clients at the beginning of the game.
    /// </summary>
    [Serializable]
    public sealed class GameStartData
    {
        #region Fields
        private int _turnNumber = 1;
        private ITextDatabase _textDatabase;
        private GameOptions _options;
        private GameMod _gameMod;
        private RaceDatabase _races;
        private CivDatabase _civilizations;
        private TechDatabase _techDatabase;
        private ResearchMatrix _researchMatrix;
        private CivilizationManager _civManager;
        private GameTables _tables;
        private UniverseManager _universe;
        private SectorClaimGrid _sectorClaims;
        private TechTreeMap _techTrees;
        private CivilizationPairedMap<DiplomacyStatus> _diplomacyStatus;
        private RelationshipMap _relationships;
        private Diplomat _diplomat;
        private StrategyDatabase _strategyDatabase;
        private AgentDatabase _agentDatabase;
        #endregion

        /// <summary>
        /// Creates the local game context useing the data in this <see cref="GameStartData"/> instance.
        /// </summary>
        /// <returns>The new game context.</returns>
        public GameContext CreateLocalGame()
        {
            GameContext game = new GameContext();
            GameContext.Push(game);
            try
            {
                game.TurnNumber = _turnNumber;
                game.Options = _options;
                game.GameMod = _gameMod;
                game.Civilizations = _civilizations;
                game.CivilizationManagers = new CivilizationManagerMap { _civManager };
                game.Races = _races;
                game.Universe = _universe;
                game.TechDatabase = _techDatabase;
                game.Tables = _tables;
                game.ResearchMatrix = _researchMatrix;
                game.SectorClaims = _sectorClaims;
                game.TechTrees = _techTrees;
                game.AgentDatabase = _agentDatabase;
                game.StrategyDatabase = _strategyDatabase;
                game.DiplomacyStatus = _diplomacyStatus;
                game.Relationships = _relationships;
                game.Diplomats = new CivilizationKeyedMap<Diplomat>(o => o.OwnerID);
                if (_diplomat != null)
                    game.Diplomats.Add(_diplomat);
                game.OnDeserialized();
                game.LoadStrings(_textDatabase);
            }
            finally
            {
                GameContext.Pop();
            }
            return game;
        }

        /// <summary>
        /// Creates a new <see cref="GameStartData"/> instance for a specified player using
        /// the given game context.
        /// </summary>
        /// <param name="game">The game context.</param>
        /// <param name="player">The player.</param>
        /// <param name="textDatabase">The text database.</param>
        /// <returns>The new <see cref="GameStartData"/> instance.</returns>
        public static GameStartData Create(GameContext game, Player player, ITextDatabase textDatabase)
        {
            if (game == null)
                throw new ArgumentNullException("game");
            if (player == null)
                throw new ArgumentNullException("player");

            var data = new GameStartData();

            GameContext.Push(game);

            try
            {
                data._textDatabase = textDatabase;
                data._turnNumber = game.TurnNumber;
                data._options = game.Options;
                data._gameMod = game.GameMod;
                data._civilizations = game.Civilizations;
                data._civManager = game.CivilizationManagers[player.EmpireID];
                data._races = game.Races;
                data._universe = game.Universe;
                data._techDatabase = game.TechDatabase;
                data._tables = game.Tables;
                data._researchMatrix = game.ResearchMatrix;
                data._sectorClaims = game.SectorClaims;
                data._techTrees = game.TechTrees;
                data._agentDatabase = game.AgentDatabase;
                data._strategyDatabase = game.StrategyDatabase;
                data._diplomacyStatus = game.DiplomacyStatus;
                data._relationships = new RelationshipMap(
                    game.Relationships.Where(
                        o => (o.OwnerCivID == player.EmpireID) || (o.OtherCivID == player.EmpireID)));
                //data._diplomat = game.Diplomats[player.EmpireID];

                data._civManager.Compact();
            }
            finally
            {
                GameContext.Pop();
            }

            return data;
        }
    }
}
